package trunk.gui;

import trunk.component.*;
import trunk.control.*;
import trunk.res.R;

import javax.swing.*;
import java.awt.*;
import java.util.*;

/**
 * panel for display the simulation, it is just like a canvas, it will contain registers, ALU and buses
 * Created by IntelliJ IDEA.
 * User: yipeipei
 * Date: 11/28/11
 * Time: 10:55 PM
 * To change this template use File | Settings | File Templates.
 */
public class SimulatePanel extends JPanel {
    private int dashRect_x = 20;
    private int dashRect_y = 80;
    private int dashRect_width = 350;
    private int dashRect_height = 400;

    //bus
    protected Line[] AB;    //address bus
    protected Line[] DB;    //data bus
    protected Line[] CB;    //control bus
    protected Line[] IB;    //internal bus

    //ALU and its neighbours
    protected Register selectA; //selector A
    protected Register selectB; //selector B
    protected ALU alu;  //ALU
    protected Register shifter;   //shifter

    //registers
    protected Register R0;
    protected Register R1;
    protected Register R2;
    protected Register R3;
    protected Register C;
    protected Register D;

    protected Register MAR;
    protected Register MDR;
    protected Register IR;
    protected Register PC;
    protected Register SP;
    protected Register PSW;

    //use a register to simulate the following components
    //  protected Register CL;  //control logic
    protected Register M;
    protected Register IF1; //interface 1
    protected Register IF2;
    protected Register IO1; //input/output device 1
    protected Register IO2;

    //joint lines groups

    //arrowline
    protected ArrowLine arr_shift;
    protected ArrowLine arr_alu;
    protected ArrowLine arr_c0;
    protected ArrowLine arr_a;
    protected ArrowLine arr_b;
    protected ArrowLine arr_sele1;
//    protected ArrowLine arr_sele2;
    protected ArrowLine arr_sele3;
 //   protected ArrowLine arr_sele4;
    protected ArrowLine arr_r0;
    protected ArrowLine arr_mar;
    protected ArrowLine arr_r1;
    protected ArrowLine arr_mdr;
    protected ArrowLine arr_r2;
    protected ArrowLine arr_ir;
    protected ArrowLine arr_r3;
    protected ArrowLine arr_pc;
    protected ArrowLine arr_c;
    protected ArrowLine arr_sp;
    protected ArrowLine arr_d;
    protected ArrowLine arr_psw;
    protected ArrowLine arr_ab2m;
    protected ArrowLine arr_db2m;
    protected ArrowLine arr_m2db;
    protected ArrowLine arr_cb2m;
    protected ArrowLine arr_m2cb;

    protected ArrowLine arr_mar2ab;
    protected Line arr_marL;
    protected ArrowLine arr_mdr2db;
    protected Line arr_mdr2dbL;
    protected ArrowLine arr_db2mdr;
    protected Line arr_db2mdrL;
    protected ArrowLine arr_db2ir;
    protected Line arr_db2irL;

    /*combine components above to get a component group*/
    private ArrayList<StatusAlterable> CG_M2IR = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_PC2A = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_A2ALU = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_C02ALU = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_ALU2MOVE = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2PC = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_R02A = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2MAR = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_M2MDR = new ArrayList<StatusAlterable>();        
    private ArrayList<StatusAlterable> CG_MDR2B = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_B2ALU = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2C = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2R0 = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_C2A = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_R02B = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_R12A = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2R1 = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2D = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_D2A = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_R12B = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MOVE2MDR = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_MDR2M = new ArrayList<StatusAlterable>();
    private ArrayList<StatusAlterable> CG_D2B = new ArrayList<StatusAlterable>();
   
            
    // protected ArrowLine arr;

    public SimulatePanel() {
        super(true);    //null for do not use a layout, true for enable double buffer
        this.setBounds(0, 0, R.attribute.SIM_PANEL_WIDTH, R.attribute.SIM_PANEL_HEIGHT);    //set a fixed location in its container
        this.setBorder(R.attribute.BORDER);

        initialize();
        initializeGroup();  //sort the component into group


        this.setVisible(true);

    }

    private void initialize() {
        //initialize address bus
        AB = new Line[5];
        {
            AB[0] = new Line(20, 20, Direction.RIGHT, 335);
            AB[1] = new Line(AB[0].getxEnd(), AB[0].getyEnd(), Direction.RIGHT, 70);
            AB[2] = new Line(AB[1].getxEnd(), AB[1].getyEnd(), Direction.RIGHT, 60);
            AB[3] = new Line(AB[2].getxEnd(), AB[2].getyEnd(), Direction.RIGHT, 60);
            AB[4] = new Line(AB[3].getxEnd(), AB[3].getyEnd(), Direction.RIGHT, 10);
        }

        //initialize data bus
        DB = new Line[6];
        {
            DB[0] = new Line(20, 40, Direction.RIGHT, 355);
            DB[1] = new Line(DB[0].getxEnd(), DB[0].getyEnd(), Direction.RIGHT, 20);
            DB[2] = new Line(DB[1].getxEnd(), DB[1].getyEnd(), Direction.RIGHT, 50);
            DB[3] = new Line(DB[2].getxEnd(), DB[2].getyEnd(), Direction.RIGHT, 50);
            DB[4] = new Line(DB[3].getxEnd(), DB[3].getyEnd(), Direction.RIGHT, 50);
            DB[5] = new Line(DB[4].getxEnd(), DB[4].getyEnd(), Direction.RIGHT, 10);
        }

        //initialize control bus
        CB = new Line[5];
        {
            CB[0] = new Line(20, 60, Direction.RIGHT, 395);
            CB[1] = new Line(CB[0].getxEnd(), CB[0].getyEnd(), Direction.RIGHT, 50);
            CB[2] = new Line(CB[1].getxEnd(), CB[1].getyEnd(), Direction.RIGHT, 40);
            CB[3] = new Line(CB[2].getxEnd(), CB[2].getyEnd(), Direction.RIGHT, 40);
            CB[4] = new Line(CB[3].getxEnd(), CB[3].getyEnd(), Direction.RIGHT, 10);
        }

        //initialize the internal bus
        IB = new Line[8];
        {
            IB[0] = new Line(dashRect_x + 110, dashRect_y + 20, Direction.RIGHT, 160);
            IB[1] = new Line(IB[0].getxEnd(), IB[0].getyEnd(), Direction.DOWN, 30);
            IB[2] = new Line(IB[1].getxEnd(), IB[1].getyEnd(), Direction.DOWN, 60);
            IB[3] = new Line(IB[2].getxEnd(), IB[2].getyEnd(), Direction.DOWN, 60);
            IB[4] = new Line(IB[3].getxEnd(), IB[3].getyEnd(), Direction.DOWN, 60);
            IB[5] = new Line(IB[4].getxEnd(), IB[4].getyEnd(), Direction.DOWN, 60);
            IB[6] = new Line(IB[5].getxEnd(), IB[5].getyEnd(), Direction.DOWN, 60);
            IB[7] = new Line(IB[6].getxEnd(), IB[6].getyEnd(), Direction.DOWN, 10);
        }

        //initialize the shifter
        shifter = new Register(IB[0].getxStart() - R.attribute.REGISTER_WIDTH / 2, IB[0].getyStart() + 20, "移位器");

        //arrow_shift
        arr_shift = new ArrowLine(IB[0].getxStart(), shifter.getyStart(), IB[0].getxStart(), IB[0].getyStart(), Status.NORMAL);

        //initialize the ALU and arrow_alu
        alu = new ALU(shifter.getxStart() + ALU.WIDTH / 2, shifter.getyStart() + 2 * shifter.getHeight());
        arr_alu = new ArrowLine(alu.getX_UP(), alu.getY_UP(), alu.getX_UP(), alu.getY_UP() - shifter.getHeight(), Status.NORMAL);
        arr_c0 = new ArrowLine(alu.getX_UP() + alu.getWidth() + 10, alu.getY_UP() + alu.getHeight() / 2, Direction.LEFT, alu.getWidth() / 2 - 5);
        //initialize the selector and arrow_a arrow_b
        selectA = new Register(alu.getX_UP() - 5 - 55, alu.getY_UP() + 58, 55, 20, "选择器A");
        selectB = new Register(alu.getX_UP() + 5, alu.getY_UP() + 58, 55, 20, "选择器B");
        arr_a = new ArrowLine(alu.getX_UP() - ALU.WIDTH / 2, alu.getY_UP() + alu.getHeight() + 28, alu.getX_UP() - ALU.WIDTH / 2, alu.getY_UP() + 30, Status.NORMAL);
        arr_b = new ArrowLine(alu.getX_UP() + ALU.WIDTH / 2, alu.getY_UP() + alu.getHeight() + 28, alu.getX_UP() + ALU.WIDTH / 2, alu.getY_UP() + 30, Status.NORMAL);

        arr_sele1 = new ArrowLine(selectA.getxStart() + selectA.getWidth() / 2, selectA.getyStart() + 40, selectA.getxStart() + selectA.getWidth() / 2, selectA.getyStart() + 20, Status.NORMAL);
     //   arr_sele2 = new ArrowLine(selectA.getxStart() + 40, selectA.getyStart() + 40, selectA.getxStart() + 40, selectA.getyStart() + 20, Status.NORMAL);
        arr_sele3 = new ArrowLine(selectB.getxStart() + selectB.getWidth() / 2, selectB.getyStart() + 40, selectB.getxStart() + selectB.getWidth() / 2, selectB.getyStart() + 20, Status.NORMAL);
     //   arr_sele4 = new ArrowLine(selectB.getxStart() + 40, selectB.getyStart() + 40, selectB.getxStart() + 40, selectB.getyStart() + 20, Status.NORMAL);

        //initialize general registers
        int X_OFFSET = -R.attribute.REGISTER_WIDTH - 10;
        int Y_OFFSET = -10;

        R0 = new Register(IB[1].getxEnd() + X_OFFSET, IB[1].getyEnd() + Y_OFFSET, "R0");
        R1 = new Register(IB[2].getxEnd() + X_OFFSET, IB[2].getyEnd() + Y_OFFSET, "R1");
        R2 = new Register(IB[3].getxEnd() + X_OFFSET, IB[3].getyEnd() + Y_OFFSET, "R2");
        R3 = new Register(IB[4].getxEnd() + X_OFFSET, IB[4].getyEnd() + Y_OFFSET, "R3");
        C = new Register(IB[5].getxEnd() + X_OFFSET, IB[5].getyEnd() + Y_OFFSET, "C");
        D = new Register(IB[6].getxEnd() + X_OFFSET, IB[6].getyEnd() + Y_OFFSET, "D");

        arr_r0 = new ArrowLine(IB[1].getxEnd(), IB[1].getyEnd() - 3, IB[1].getxEnd() - 10, IB[1].getyEnd() - 3);
        arr_r1 = new ArrowLine(IB[2].getxEnd(), IB[2].getyEnd() - 3, IB[2].getxEnd() - 10, IB[2].getyEnd() - 3);
        arr_r2 = new ArrowLine(IB[3].getxEnd(), IB[3].getyEnd() - 3, IB[3].getxEnd() - 10, IB[3].getyEnd() - 3);
        arr_r3 = new ArrowLine(IB[4].getxEnd(), IB[4].getyEnd() - 3, IB[4].getxEnd() - 10, IB[4].getyEnd() - 3);
        arr_c = new ArrowLine(IB[5].getxEnd(), IB[5].getyEnd() - 3, IB[5].getxEnd() - 10, IB[5].getyEnd() - 3);
        arr_d = new ArrowLine(IB[6].getxEnd(), IB[6].getyEnd() - 3, IB[6].getxEnd() - 10, IB[6].getyEnd() - 3);

        X_OFFSET = 10;
        Y_OFFSET = -10;
        MAR = new Register(IB[1].getxEnd() + X_OFFSET, IB[1].getyEnd() + Y_OFFSET, "MAR");
        MDR = new Register(IB[2].getxEnd() + X_OFFSET, IB[2].getyEnd() + Y_OFFSET, "MDR");
        IR = new Register(IB[3].getxEnd() + X_OFFSET, IB[3].getyEnd() + Y_OFFSET, "IR");
        PC = new Register(IB[4].getxEnd() + X_OFFSET, IB[4].getyEnd() + Y_OFFSET, "PC");
        SP = new Register(IB[5].getxEnd() + X_OFFSET, IB[5].getyEnd() + Y_OFFSET, "SP");
        PSW = new Register(IB[6].getxEnd() + X_OFFSET, IB[6].getyEnd() + Y_OFFSET, "PSW");

        arr_mar = new ArrowLine(IB[1].getxEnd(), IB[1].getyEnd() + 3, Direction.RIGHT, 10);
        arr_mdr = new ArrowLine(IB[2].getxEnd(), IB[2].getyEnd() + 3, Direction.RIGHT, 10);
        arr_ir = new ArrowLine(IB[3].getxEnd(), IB[3].getyEnd() + 3, Direction.RIGHT, 10);
        arr_pc = new ArrowLine(IB[4].getxEnd(), IB[4].getyEnd() + 3, Direction.RIGHT, 10);
        arr_sp = new ArrowLine(IB[5].getxEnd(), IB[5].getyEnd() + 3, Direction.RIGHT, 10);
        arr_psw = new ArrowLine(IB[6].getxEnd(), IB[6].getyEnd() + 3, Direction.RIGHT, 10);

        //initialize other register like things
        //  X_OFFSET = 0;
        //   Y_OFFSET = 180;
        //   CL = new Register(CB[0].getxEnd(),CB[0].getyEnd()+Y_OFFSET,"Control\nLogic");

        //initialize memory
        X_OFFSET = -10;
        Y_OFFSET = 100;
        M = new Register(AB[1].getxEnd() + X_OFFSET, AB[1].getyEnd() + Y_OFFSET, 60, 60, 20, 35, "主存");
        arr_ab2m = new ArrowLine(AB[1].getxEnd(), AB[1].getyEnd(), Direction.DOWN, Y_OFFSET);
        arr_db2m = new ArrowLine(DB[2].getxEnd(), DB[2].getyEnd(), Direction.DOWN, Y_OFFSET - 20);
        arr_m2db = new ArrowLine(DB[2].getxEnd(), DB[2].getyEnd() + Y_OFFSET - 20, Direction.UP, Y_OFFSET - 20);
        arr_cb2m = new ArrowLine(CB[1].getxEnd(), CB[1].getyEnd(), Direction.DOWN, Y_OFFSET - 40);
        arr_m2cb = new ArrowLine(CB[1].getxEnd(), CB[1].getyEnd() + Y_OFFSET - 40, Direction.UP, Y_OFFSET - 40);

        X_OFFSET = AB[0].getxEnd() - MAR.getxStart() - MAR.getWidth();
        Y_OFFSET = 10;
        arr_mar2ab = new ArrowLine(MAR.getxStart() + MAR.getWidth() + X_OFFSET, MAR.getyStart() + MAR.getHeight() / 2, AB[0].getxEnd(), AB[0].getyEnd());
        arr_marL = new Line(MAR.getxStart() + MAR.getWidth(), MAR.getyStart() + MAR.getHeight() / 2, Direction.RIGHT, X_OFFSET);
        arr_mdr2db = new ArrowLine(MDR.getxStart() + MDR.getWidth() + X_OFFSET + 20, MDR.getyStart() + MDR.getHeight() / 2, DB[0].getxEnd(), DB[0].getyEnd());
        arr_mdr2dbL = new Line(MDR.getxStart() + MDR.getWidth() + X_OFFSET + 20, MDR.getyStart() + MDR.getHeight() / 2, DB[0].getxEnd(), DB[0].getyEnd());
        arr_db2mdr = new ArrowLine(MDR.getxStart() + MDR.getWidth() + X_OFFSET + 20, MDR.getyStart() + MDR.getHeight() / 2, MDR.getxStart() + MDR.getWidth(), MDR.getyStart() + MDR.getHeight() / 2);
        arr_db2mdrL = new Line(MDR.getxStart() + MDR.getWidth() + X_OFFSET + 20, MDR.getyStart() + MDR.getHeight() / 2, MDR.getxStart() + MDR.getWidth(), MDR.getyStart() + MDR.getHeight() / 2);
        arr_db2ir = new ArrowLine(IR.getxStart() + IR.getWidth() + X_OFFSET + 40, IR.getyStart() + IR.getHeight() / 2, IR.getxStart() + IR.getWidth(), IR.getyStart() + IR.getHeight() / 2);
        arr_db2irL = new Line(IR.getxStart() + IR.getWidth() + X_OFFSET + 40, IR.getyStart() + IR.getHeight() / 2, DB[1].getxEnd(), DB[1].getyEnd());
    }

    private void initializeGroup() {
        //initialize M2IR
        {
            CG_M2IR.add(this.M);
            CG_M2IR.add(this.arr_m2db);
            CG_M2IR.add(this.DB[2]);
            CG_M2IR.add(this.arr_db2irL);
            CG_M2IR.add(this.arr_db2ir);
            CG_M2IR.add(this.IR);
        }
        {
            CG_PC2A.add(this.PC);
            CG_PC2A.add(this.arr_sele1);
            CG_PC2A.add(this.selectA);
        }
        {
            CG_A2ALU.add(this.selectA);
            CG_A2ALU.add(this.arr_a);
            CG_A2ALU.add(this.alu);           
        }
        {
            CG_C02ALU.add(this.arr_c0);
            CG_C02ALU.add(this.alu);
        }
        {
            CG_ALU2MOVE.add(this.alu);
            CG_ALU2MOVE.add(this.arr_alu);
            CG_ALU2MOVE.add(this.shifter);
        }
        {
            CG_MOVE2PC.add(this.shifter);
            CG_MOVE2PC.add(this.arr_shift);
            CG_MOVE2PC.add(this.IB[0]);
            CG_MOVE2PC.add(this.IB[1]);
            CG_MOVE2PC.add(this.IB[2]);
            CG_MOVE2PC.add(this.IB[3]);
            CG_MOVE2PC.add(this.IB[4]);
            CG_MOVE2PC.add(this.arr_pc);
            CG_MOVE2PC.add(this.PC);
        }
        {
            CG_R02A.add(this.R0);
            CG_R02A.add(this.arr_sele1);
            CG_R02A.add(this.selectA);
        }
        {
            CG_MOVE2MAR.add(this.shifter);
            CG_MOVE2MAR.add(this.arr_shift);
            CG_MOVE2MAR.add(this.IB[0]);
            CG_MOVE2MAR.add(this.IB[1]);
            CG_MOVE2MAR.add(this.arr_mar);
            CG_MOVE2MAR.add(this.MAR);
        }
        {
            CG_M2MDR.add(this.M);
            CG_M2MDR.add(this.arr_m2db);
            CG_M2MDR.add(this.DB[2]);
            CG_M2MDR.add(this.DB[1]);
            CG_M2MDR.add(this.arr_mdr2dbL);
            CG_M2MDR.add(this.arr_db2mdr);
            CG_M2MDR.add(this.MDR);
        }
        {
            CG_MDR2B.add(this.MDR);
            CG_MDR2B.add(this.arr_sele3);
            CG_MDR2B.add(this.selectB);
        }
        {
            CG_B2ALU.add(this.selectB);
            CG_B2ALU.add(this.arr_b);
            CG_B2ALU.add(this.alu);
        }
        {
            CG_MOVE2C.add(this.shifter);
            CG_MOVE2C.add(this.arr_shift);
            CG_MOVE2C.add(this.IB[0]);
            CG_MOVE2C.add(this.IB[1]);
            CG_MOVE2C.add(this.IB[2]);
            CG_MOVE2C.add(this.IB[3]);
            CG_MOVE2C.add(this.IB[4]);
            CG_MOVE2C.add(this.IB[5]);
            CG_MOVE2C.add(this.arr_c);
            CG_MOVE2C.add(this.C);
        }
        {
            CG_MOVE2R0.add(this.shifter);
            CG_MOVE2R0.add(this.arr_shift);
            CG_MOVE2R0.add(this.IB[0]);
            CG_MOVE2R0.add(this.IB[1]);
            CG_MOVE2R0.add(this.arr_r0);
            CG_MOVE2R0.add(this.R0);
        }
        {
            CG_C2A.add(this.C);
            CG_C2A.add(this.arr_sele1);
            CG_C2A.add(this.selectA);
        }
        {
            CG_R02B.add(this.R0);
            CG_R02B.add(this.arr_sele3);
            CG_R02B.add(this.selectB);
        }
        {
            CG_R12A.add(this.R1);
            CG_R12A.add(this.arr_sele1);
            CG_R12A.add(this.selectA);
        }
        {
            CG_MOVE2R1.add(this.shifter);
            CG_MOVE2R1.add(this.arr_shift);
            CG_MOVE2R1.add(this.IB[0]);
            CG_MOVE2R1.add(this.IB[1]);
            CG_MOVE2R1.add(this.IB[2]);
            CG_MOVE2R1.add(this.arr_r1);
            CG_MOVE2R1.add(this.R1);
        }
        {
            CG_MOVE2D.add(this.shifter);
            CG_MOVE2D.add(this.arr_shift);
            CG_MOVE2D.add(this.IB[0]);
            CG_MOVE2D.add(this.IB[1]);
            CG_MOVE2D.add(this.IB[2]);
            CG_MOVE2D.add(this.IB[3]);
            CG_MOVE2D.add(this.IB[4]);
            CG_MOVE2D.add(this.IB[5]);
            CG_MOVE2D.add(this.IB[6]);
            CG_MOVE2D.add(this.arr_d);
            CG_MOVE2D.add(this.D);
        }
        {
            CG_D2A.add(this.D);
            CG_D2A.add(this.arr_sele1);
            CG_D2A.add(this.selectA);
        }
        {
            CG_R12B.add(this.R1);
            CG_R12B.add(this.arr_sele3);
            CG_R12B.add(this.selectB);
        }
        {
            CG_MOVE2MDR.add(this.shifter);
            CG_MOVE2MDR.add(this.arr_shift);
            CG_MOVE2MDR.add(this.IB[0]);
            CG_MOVE2MDR.add(this.IB[1]);
            CG_MOVE2MDR.add(this.IB[2]);
            CG_MOVE2MDR.add(this.arr_mdr);
            CG_MOVE2MDR.add(this.MDR);
        }
        {
            CG_MDR2M.add(this.MDR);
            CG_MDR2M.add(this.arr_db2mdrL);
            CG_MDR2M.add(this.arr_mdr2db);
            CG_MDR2M.add(this.DB[1]);
            CG_MDR2M.add(this.DB[2]);
            CG_MDR2M.add(this.arr_db2m);
            CG_MDR2M.add(this.M);
        }
        {
            CG_D2B.add(this.D);
            CG_D2B.add(this.arr_sele3);
            CG_D2B.add(this.selectB);
        }
    
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        //change stroke to draw a line in dash stroke
        g2d.setStroke(R.drawable.STROKE_DASHED);
        g2d.drawRect(dashRect_x, dashRect_y, dashRect_width, dashRect_height);
        g2d.setStroke(R.drawable.STROKE_DEFAULT);   //restore the default stroke

        //draw AB
        for (Line line : AB) {
            line.paint(g);
        }
        g.drawString("AB", AB[4].getxEnd() + 10, AB[4].getyEnd() + 6);

        //draw DB
        for (Line line : DB) {
            line.paint(g);
        }
        g.drawString("DB", DB[5].getxEnd() + 10, DB[5].getyEnd() + 6);

        //draw CB
        for (Line line : CB) {
            line.paint(g);
        }
        g.drawString("CB", CB[4].getxEnd() + 10, CB[4].getyEnd() + 6);

        //draw IB
        for (Line line : IB) {
            line.paint(g);
        }
        g.drawString("内总线", (IB[0].getxStart() + IB[0].getxEnd()) / 2 - 15, IB[0].getyEnd() - 6);

        //draw shifter
        shifter.paint(g);

        //draw arrow_shift
        arr_shift.paint(g);
        //draw ALU       
        alu.paint(g);
        arr_alu.paint(g);
        arr_c0.paint(g);
        g.drawString("C0", arr_c0.getxStart() + 5, arr_c0.getyStart() + 4);

        //draw selector
        selectA.paint(g);
        selectB.paint(g);
        arr_a.paint(g);
        arr_b.paint(g);
        arr_sele1.paint(g);
      //  arr_sele2.paint(g);
        arr_sele3.paint(g);
      //  arr_sele4.paint(g);

        g.drawString("R0…R3", arr_sele1.getxStart() - 20, arr_sele1.getyStart() + 12);
        g.drawString(" C、D", arr_sele1.getxStart() - 20, arr_sele1.getyStart() + 24);
        g.drawString("PC、SP", arr_sele1.getxStart() - 20, arr_sele1.getyStart() + 36);
        g.drawString("R0…R3", arr_sele3.getxStart() - 20, arr_sele1.getyStart() + 12);
        g.drawString(" C、D", arr_sele3.getxStart() - 20, arr_sele1.getyStart() + 24);
        g.drawString("PSW、MDR", arr_sele3.getxStart() - 20, arr_sele1.getyStart() + 36);

        //draw registers
        R0.paint(g);
        R1.paint(g);
        R2.paint(g);
        R3.paint(g);
        C.paint(g);
        D.paint(g);
        MAR.paint(g);
        MDR.paint(g);
        IR.paint(g);
        PC.paint(g);
        SP.paint(g);
        PSW.paint(g);

        arr_r0.paint(g);
        arr_r1.paint(g);
        arr_r2.paint(g);
        arr_r3.paint(g);
        arr_c.paint(g);
        arr_d.paint(g);
        arr_mar.paint(g);
        arr_mdr.paint(g);
        arr_ir.paint(g);
        arr_pc.paint(g);
        arr_sp.paint(g);
        arr_psw.paint(g);

        // CL.paint(g);
        M.paint(g);
        arr_ab2m.paint(g);
        arr_db2m.paint(g);
        arr_m2db.paint(g);
        arr_cb2m.paint(g);
        arr_m2cb.paint(g);
        arr_mar2ab.paint(g);
        arr_marL.paint(g);
        arr_mdr2db.paint(g);
        arr_mdr2dbL.paint(g);
        arr_db2mdr.paint(g);
        arr_db2mdrL.paint(g);
        arr_db2ir.paint(g);
        arr_db2irL.paint(g);
    }

    //schedule a task
    private void actionPerform(ArrayList<StatusAlterable> componentList) {
         Control.getInstant().timer.schedule(new StatusAlterTask(componentList), 0);
    }
    private void notactionPerform(ArrayList<StatusAlterable> componentList) {
        Control.getInstant().timer.schedule(new StatusAlterTask(componentList,1), 0);
    }
    
    public void clearaction(){
        notactionPerform(CG_M2IR);
        notactionPerform(CG_PC2A);
        notactionPerform(CG_A2ALU);
        notactionPerform(CG_C02ALU);
        notactionPerform(CG_M2IR);
        notactionPerform(CG_ALU2MOVE);
        notactionPerform(CG_MOVE2PC);
        notactionPerform(CG_R02A);
        notactionPerform(CG_MOVE2MAR);
        notactionPerform(CG_M2MDR);
        notactionPerform(CG_MDR2B);
        notactionPerform(CG_B2ALU);
        notactionPerform(CG_MOVE2C);
        notactionPerform(CG_MOVE2R0);
        notactionPerform(CG_C2A);
        notactionPerform(CG_R02B);
        notactionPerform(CG_R12A);
        notactionPerform(CG_MOVE2R1);
        notactionPerform(CG_MOVE2D);
        notactionPerform(CG_D2A);
        notactionPerform(CG_R12B);
        notactionPerform(CG_MOVE2MDR);
        notactionPerform(CG_MDR2M);
        notactionPerform(CG_D2B);
    }
    public void M2IR() {
        actionPerform(CG_M2IR);
    }
    public void PC2A() {
        actionPerform(CG_PC2A);
    }
    public void A2ALU() {
        actionPerform(CG_A2ALU);
    }
    public void C02ALU() {
        actionPerform(CG_C02ALU);
    }
    public void ALU2MOVE() {
        actionPerform(CG_ALU2MOVE);
    }
    public void MOVE2PC() {
        actionPerform(CG_MOVE2PC);
    }
    public void R02A() {
        actionPerform(CG_R02A);
    }
    public void MOVE2MAR() {
        actionPerform(CG_MOVE2MAR);
    }
    public void M2MDR() {
        actionPerform(CG_M2MDR);
    }
    public void MDR2B() {
        actionPerform(CG_MDR2B);
    }
    public void B2ALU() {
        actionPerform(CG_B2ALU);
    }
    public void MOVE2C() {
        actionPerform(CG_MOVE2C);
    }
    public void MOVE2R0() {
        actionPerform(CG_MOVE2R0);
    }
    public void C2A() {
        actionPerform(CG_C2A);
    }
    public void R02B() {
        actionPerform(CG_R02B);
    }
    public void R12A() {
        actionPerform(CG_R12A);
    }
    public void MOVE2R1() {
        actionPerform(CG_MOVE2R1);
    }
    public void MOVE2D() {
        actionPerform(CG_MOVE2D);
    }
    public void D2A() {
        actionPerform(CG_D2A);
    }
    public void R12B() {
        actionPerform(CG_R12B);
    }
    public void MOVE2MDR() {
        actionPerform(CG_MOVE2MDR);
    }
    public void MDR2M() {
        actionPerform(CG_MDR2M);
    }
    public void D2B() {
        actionPerform(CG_D2B);
    }
   
}
